package grape.wx.rest.mp.basic.mvc;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import grape.common.exception.ExceptionTools;
import grape.common.exception.runtime.BadRequestException;
import grape.common.rest.form.BasePageForm;
import grape.common.rest.mvc.SuperController;
import grape.wx.rest.mp.basic.form.UploadFileForm;
import grape.wx.rest.mp.basic.form.WxMpMaterialForm;
import grape.wx.rest.mp.basic.mapper.MpMaterialWebMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.*;
import me.chanjar.weixin.mp.bean.tag.WxUserTag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.util.List;

/**
 * Created by yangwei
 * Created at 2020/7/20 20:48
 */
@RestController
@RequestMapping("/wx/mp/material/{appId}")
@Api(tags = "公众号素材相关接口")
public class MpMaterialController extends SuperController {

    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private MpMaterialWebMapper mpMaterialWebMapper;


    /**
     * 图文永久素材创建接口
     * @param appId
     * @param news
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材图文创建接口")
    @ResponseStatus(HttpStatus.CREATED)
    @PreAuthorize("hasAuthority('wx:mp:material:create')")
    @PostMapping("/create/news")
    public WxMpMaterialUploadResult permanentNewsCreate(@PathVariable String appId,@RequestBody WxMpMaterialNews news) throws WxErrorException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialNewsUpload(news);
    }
    /**
     * 永久素材其他类型（图片、语音、视频）创建接口
     * @param appId
     * @param type 类型
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材其他类型（图片、语音、视频）创建接口")
    @ResponseStatus(HttpStatus.CREATED)
    @PreAuthorize("hasAuthority('wx:mp:material:create')")
    @PostMapping(value = "/create/file/{type}")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "form", dataType="__file", name = "file",
            value = "上传的文件", required = true)})
    public WxMpMaterialUploadResult permanentFileCreate(@PathVariable String appId, @PathVariable String type, WxMpMaterialForm materialForm, @Valid UploadFileForm uploadFileForm) throws WxErrorException, IOException {
        File tempFile = tempFileMap(uploadFileForm.getFile());
        WxMpMaterial material = mpMaterialWebMapper.map(materialForm);
        material.setFile(tempFile);
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialFileUpload(type,material);
    }
    /**
     * 永久素材上传图文消息内的图片获取URL接口
     * @param appId
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材上传图文消息内的图片获取URL接口")
    @ResponseStatus(HttpStatus.CREATED)
    @PreAuthorize("hasAuthority('wx:mp:material:create')")
    @PostMapping(value = "/create/mediaimg")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "form", dataType="__file", name = "file",
            value = "上传的文件", required = true)})
    public WxMediaImgUploadResult permanentFileCreate(@PathVariable String appId, @Valid UploadFileForm uploadFileForm) throws WxErrorException, IOException {
        File tempFile = tempFileMap(uploadFileForm.getFile());
        return this.wxMpService.switchoverTo(appId).getMaterialService().mediaImgUpload(tempFile);
    }

    /**
     * 将上传的文件转为临时本地文件
     * @param file
     * @return
     * @throws IOException
     */
    private File tempFileMap(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        int extDotIndex = originalFilename.lastIndexOf(".");
        if(extDotIndex < 0){
            throw new BadRequestException("文件格式不正确 ，没有扩展名");
        }
        String ext = originalFilename.substring(extDotIndex + 1);
        if(isStrEmpty(ext)){
            throw new BadRequestException("文件格式不正确 ，没有扩展名");

        }
        File tempFile = FileUtils.createTmpFile(file.getInputStream(),file.getName(),ext);
        return tempFile;
    }
    /**
     * 永久素材其他类型（图片、语音、视频）创建接口
     * @param appId
     * @param mediaId
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材删除接口")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    @PreAuthorize("hasAuthority('wx:mp:material:delete')")
    @DeleteMapping("/delete/{mediaId}")
    public Boolean permanentMaterialDelete(@PathVariable String appId,@PathVariable String mediaId) throws WxErrorException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialDelete(mediaId);
    }
    /**
     * 永久素材图文更新接口
     * @param appId
     * @param wxMpMaterialArticleUpdate
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材图文更新接口")
    @ResponseStatus(HttpStatus.CREATED)
    @PreAuthorize("hasAuthority('wx:mp:material:update')")
    @PutMapping("/update/news")
    public Boolean permanentNewsUpdate(@PathVariable String appId,@RequestBody WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdate);
    }
    /**
     * 临时素材创建接口
     * @param appId
     * @param mediaType
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("临时素材创建接口")
    @ResponseStatus(HttpStatus.CREATED)
    @PreAuthorize("hasAuthority('wx:mp:material:create')")
    @PostMapping(value="/create/media/{mediaType}")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "form", dataType="__file", name = "file",
            value = "上传的文件", required = true)})
    public WxMediaUploadResult temporaryMediaCreate(@PathVariable String appId, @PathVariable String mediaType, @Valid UploadFileForm uploadFileForm) throws WxErrorException, IOException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().mediaUpload(mediaType,tempFileMap(uploadFileForm.getFile()));
    }


    /**
     * 临时素材创建接口
     * @param appId
     * @param mediaId
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("临时素材获取接口")
    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/get/media/{mediaId}")
    public void temporaryMediaGet(@PathVariable String appId, @PathVariable String mediaId, HttpServletResponse response) throws WxErrorException, IOException {
        File file = this.wxMpService.switchoverTo(appId).getMaterialService().mediaDownload(mediaId);
        if (file == null) {
            throw ExceptionTools.dataNotExistRE("未下载成功，不存在");
        }
        InputStream inputStream = new FileInputStream(file);
        OutputStream stream = response.getOutputStream();
        IoUtil.copy(inputStream,stream);
        IoUtil.close(inputStream);
        IoUtil.close(stream);
    }
    /**
     * 永久素材图文分页列表获取接口
     * @param appId
     * @param pageForm
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材图文分页列表获取接口")
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasAuthority('wx:mp:material:listPage')")
    @GetMapping("/news/listPage")
    public IPage<WxMpMaterialNewsBatchGetResult.WxMaterialNewsBatchGetNewsItem> permanentNewsListPage(@PathVariable String appId, BasePageForm pageForm) throws WxErrorException {
        int offset = new Long ((pageForm.getCurrent() - 1) * pageForm.getSize()).intValue();
        int count = pageForm.getSize().intValue() ;
        WxMpMaterialNewsBatchGetResult wxMpMaterialNewsBatchGetResult = this.wxMpService.switchoverTo(appId).getMaterialService().materialNewsBatchGet(offset, count);
        Page page = new Page(pageForm.getCurrent(), pageForm.getSize(),wxMpMaterialNewsBatchGetResult.getTotalCount());
        page.setRecords(wxMpMaterialNewsBatchGetResult.getItems());
        return page;
    }

    /**
     * 永久素材其他类型（图片、语音、视频）分页列表获取接口
     * @param appId
     * @param pageForm
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材其他类型（图片、语音、视频）分页列表获取接口")
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasAuthority('wx:mp:material:listPage')")
    @GetMapping("/media/{type}/listPage")
    public IPage<WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem> permanentFileListPage(@PathVariable String appId, @PathVariable String type, BasePageForm pageForm) throws WxErrorException {
        int offset = new Long ((pageForm.getCurrent() - 1) * pageForm.getSize()).intValue();
        int count = pageForm.getSize().intValue() ;
        WxMpMaterialFileBatchGetResult wxMpMaterialFileBatchGetResult = this.wxMpService.switchoverTo(appId).getMaterialService().materialFileBatchGet(type, offset, count);
        Page page = new Page(pageForm.getCurrent(), pageForm.getSize(),wxMpMaterialFileBatchGetResult.getTotalCount());
        page.setRecords(wxMpMaterialFileBatchGetResult.getItems());
        return page;
    }
    /**
     * 永久素材声音或者图片获取接口
     * @param appId
     * @param mediaId
     * @param response
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材声音或者图片获取接口")
    @ResponseStatus(HttpStatus.OK)
    @GetMapping("/imageOrVoice/{mediaId}")
    public void permanentImageOrVoice(@PathVariable String appId,@PathVariable String mediaId, HttpServletResponse response) throws WxErrorException, IOException {
        InputStream inputStream = this.wxMpService.switchoverTo(appId).getMaterialService().materialImageOrVoiceDownload(mediaId);
        if (inputStream == null) {
            throw ExceptionTools.dataNotExistRE("未下载成功，不存在");
        }
        OutputStream stream = response.getOutputStream();
        IoUtil.copy(inputStream,stream);
        IoUtil.close(inputStream);
        IoUtil.close(stream);
    }

    /**
     * 永久素材视频获取接口
     * @param appId
     * @param mediaId
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材视频获取接口")
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasAuthority('wx:mp:material:get')")
    @GetMapping("/video/{mediaId}")
    public WxMpMaterialVideoInfoResult permanentVideoInfo(@PathVariable String appId,@PathVariable String mediaId) throws WxErrorException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialVideoInfo(mediaId);

    }
    /**
     * 永久素材图文获取接口
     * @param appId
     * @param mediaId
     * @return
     * @throws WxErrorException
     */
    @ApiOperation("永久素材图文获取接口")
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasAuthority('wx:mp:material:get')")
    @GetMapping("/news/{mediaId}")
    public WxMpMaterialNews permanentNewsInfo(@PathVariable String appId,@PathVariable String mediaId) throws WxErrorException {
        return this.wxMpService.switchoverTo(appId).getMaterialService().materialNewsInfo(mediaId);

    }
}
